﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace TileEditor01
{
    public class Tiles
    {
        public const int TILE_EMPTY = 0;
        public const int TILE_PORTAL = 1;
        public const int TILE_SPIKES = 2;
        public const int TILE_GROUND = 3;
        public const int TILE_SOUL = 4;
        public const int TILE_ENEMY = 5;
        public const int TILE_PLAYER = 6;
        public int tileRowCount = 0;
        public int tileColCount = 0;
        public int tileWidth = 0;
        public int tileHeight = 0;

        public string currentType = "Ground";
        public Rectangle tileSelectionRect = new Rectangle(0, 0, 32, 32);
        public Point tileSelected = new Point(0, 0);
        public Point pervTileSelected = new Point(0, 0);

        //public Bitmap tileSet;

        public Bitmap bitmap_Ground;
        public Bitmap bitmap_Player;
        public Bitmap bitmap_Portal;
        public Bitmap bitmap_Enemy;
        public Bitmap bitmap_Soul;
        public Bitmap bitmap_Spike;

        public struct Tile
        {
            public Tile(int tile)
            {
                tileType = tile;
                portalTo = "default";
            }
            public Tile(int tile, string portalTo)
            {
                this.tileType = tile;
                this.portalTo = new String(portalTo.ToCharArray());
            }
            public Tile(Tile old)
            {
                this.tileType = old.tileType;
                if (!String.IsNullOrEmpty(old.portalTo))
                    this.portalTo = old.portalTo.ToString();
                else this.portalTo = "default";
            }
            public int tileType;
            public String portalTo;

            internal string tileTypeToString()
            {
                switch(tileType)
                {
                    case Tiles.TILE_EMPTY:
                        return "Empty";
                    case Tiles.TILE_PORTAL:
                        return "Portal";
                    case Tiles.TILE_SPIKES:
                        return "Spikes";
                    case Tiles.TILE_GROUND:
                        return "Ground";
                    case Tiles.TILE_SOUL:
                        return "Soul";
                    case Tiles.TILE_ENEMY:
                        return "Enemy";
                    case Tiles.TILE_PLAYER:
                        return "Player";
                }
                return "Not Implemented";
            }
        }

        public Tile[,] tileArray;

        public Tiles(int w, int h, int col, int row, int set)
        {
            tileArray = new Tile[col,row];
            for (int i = 0; i < col; ++i)
                for (int j = 0; j < row; ++j)
                    tileArray[i,j] = new Tile(TILE_EMPTY);
            tileRowCount = row;
            tileColCount = col;
            tileWidth = w;
            tileHeight = h;

            //tileSet = Properties.Resources.super4x4x64x64;
            bitmap_Ground = Properties.Resources.ground;
            bitmap_Player = Properties.Resources.player;
            bitmap_Portal = Properties.Resources.portal;
            bitmap_Enemy  = Properties.Resources.enemy;
            bitmap_Soul   = Properties.Resources.soul;
            bitmap_Spike  = Properties.Resources.saw;
        }

        public void initSelectionRect(int x, int y, int width, int height)
        {
            tileSelectionRect = new Rectangle(x, y, width, height);
        }

        public void updateSelectionRectLocation(int x, int y)
        {
            if (x < 0 || x >= bitmap_Player.Width || y < 0 || y >= bitmap_Player.Height)
                return;
            tileSelectionRect.X = x;
            tileSelectionRect.Y = y;

            clampSelectionRect();
        }

        public void clampSelectionRect()
        {
            tileSelectionRect.X /= tileSelectionRect.Width;
            tileSelectionRect.Y /= tileSelectionRect.Height;

            tileSelectionRect.X = tileSelectionRect.X * tileSelectionRect.Width;
            tileSelectionRect.Y = tileSelectionRect.Y * tileSelectionRect.Height;//clamp it

        }

        public void updateWidth(int w)
        {
            tileWidth = w;
        }
        public void updateHeight(int h)
        {
            tileHeight = h;
        }
        public void updateRow(int r)
        {
            if (r > tileRowCount)
            {
                Tile[,] newTileArray = new Tile[tileColCount,r];

                for (int i = 0; i < tileColCount; ++i)
                    for (int j = 0; j < r; ++j)
                        newTileArray[i, j] = new Tile(TILE_EMPTY);

                for (int i = 0; i < tileRowCount; ++i)
                    for (int j = 0; j < tileColCount; ++j)
                        newTileArray[j, i] = new Tile(tileArray[j,i]);
                tileArray = newTileArray;
            }
            tileRowCount = r;
        }
        public void updateCol(int c)
        {
            if (c > tileColCount)
            {
                Tile[,] newTileArray = new Tile[c, tileRowCount];

                for (int i = 0; i < c; ++i)
                    for (int j = 0; j < tileRowCount; ++j)
                        newTileArray[i, j] = new Tile(TILE_EMPTY);

                for (int i = 0; i < tileRowCount; ++i)
                    for (int j = 0; j < tileColCount; ++j)
                        newTileArray[j, i] = new Tile(tileArray[j, i]);
                tileArray = newTileArray;
            }
            tileColCount = c;
        }
        public void updateSelectionRectWidth(int w)
        {
            tileSelectionRect.Width = w;
        }
        public void updateSelectionRectHeight(int h)
        {
            tileSelectionRect.Height = h;
        }

        public Point overrideTile(int x, int y, String currentType)
        {
            this.currentType = currentType;
            return overrideTile(x, y);
        }
        public Point overrideTile(int x, int y)
        {
            x /= tileWidth;
            y /= tileHeight;
            if (x < 0 || y < 0 || x >= tileColCount || y >= tileRowCount)
                return new Point(0,0);
            if (currentType != tileArray[x, y].tileTypeToString())
            {
                switch (currentType)
                {
                    case "Ground":
                        tileArray[x, y] = new Tile(TILE_GROUND);
                        break;
                    case "Spike":
                        tileArray[x, y] = new Tile(TILE_SPIKES);
                        break;
                    case "Player":
                        tileArray[x, y] = new Tile(TILE_PLAYER);
                        break;
                    case "Soul":
                        tileArray[x, y] = new Tile(TILE_SOUL);
                        break;
                    case "Enemy":
                        tileArray[x, y] = new Tile(TILE_ENEMY);
                        break;
                    case "Portal":
                        tileArray[x, y] = new Tile(TILE_PORTAL);
                        break;
                }
            }
            changeSelectedTile(x, y);
            return new Point(x,y);
        }

        internal Point clearTile(int x, int y)
        {
            x /= tileWidth;
            y /= tileHeight;
            if (x < 0 || y < 0 || x >= tileColCount || y >= tileRowCount)
                return new Point(0, 0);

            tileArray[x, y] = new Tile(TILE_EMPTY);
            changeSelectedTile(x, y);
            return new Point(x, y);
        }
        internal Point selectedTile(int x, int y)
        {
            x /= tileWidth;
            y /= tileHeight;
            if (x < 0 || y < 0 || x >= tileColCount || y >= tileRowCount)
                return new Point(0, 0);
            changeSelectedTile(x, y);
            return new Point(x, y);
        }
        public void changeSelectedTile(int x, int y)
        {
            pervTileSelected.X = tileSelected.X;
            pervTileSelected.Y = tileSelected.Y;
            tileSelected.X = x;
            tileSelected.Y = y;

        }
    }
}
